Feat(notifications): What's New — featured item hero + also-new accordion#6
Draft
avivu wants to merge 27 commits into
Draft
Feat(notifications): What's New — featured item hero + also-new accordion#6avivu wants to merge 27 commits into
avivu wants to merge 27 commits into
Conversation
9484ad8 to
3bda21d
Compare
- Add featured item hero layout (image, title, chip overlay) - Add "Also new" collapsed accordion list for non-featured items - New WhatsNewItemCollapsed component with expand/collapse, chevron icon, and per-item unread dot (opacity-based, no layout shift) - Lift seenItemIds state to WhatsNew so it survives drawer close/reopen - Badge (bar button + editor app bar) decrements per item via e-notification-item-seen window event; no 9+ cap; corner-overlap position - Auto-mark fully-visible items as seen (featured hero + all items when no featured exist) so badge clears correctly on drawer open - initialHasUnread flag suppresses dots after page refresh with 0 unread Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace custom CSS keyframe animation and absolutely-positioned Box badge with the MUI Badge component from @elementor/ui, matching the existing design-system pattern. Also restore is_unread alongside unread_count in the JS config to avoid breaking existing consumers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- editor-v1.js: revert unread_count > 0 back to is_unread (restored in PHP config) - whats-new-item.js: use insetInlineStart instead of left for RTL support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show 2-line clamped description in collapsed state (disappears when expanded) - Increase item padding from py:1.5 to py:2 (16px) for better breathing room - Align chevron to flex-start to match taller row height Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
a681418 to
71f273e
Compare
…lper - options.php: extract private get_unread_notification_ids() to eliminate duplicated transient logic between has_unread_notifications/get_unread_count - whats-new.js: wrap handleSeen with useCallback for stable reference; make setIsRead optional (default noop) so callers don't need to pass it - whats-new-drawer-content.js: add PropTypes, remove eslint-disable, use useRef for seenItemIds to cleanly satisfy exhaustive-deps - whats-new-item-collapsed.js: add PropTypes, remove eslint-disable - whats-new-item.js: use MUI variant="h6" instead of hardcoded fontSize - bar-button-notification.js: drop explicit setIsRead noop prop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Notification BarButtonNotification no longer accepts defaultIsRead — badge state is now driven by window.elementorNotifications.unread_count directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add optional `listLabel` field to featured notifications that controls the text shown in the divider above the collapsed items list. When omitted, a plain divider is rendered with no label. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…isplay wp_localize_script() converts all PHP values to strings, so unread_count: 0 becomes "0" in JS. Strict equality (0 === "0") returns false, causing the badge to display "0" even when there are no unread notifications. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…isNew Collapsing and re-expanding an item was calling onSeen again, causing the badge to double-decrement. Fix in two places: - handleSeen: only dispatch e-notification-item-seen when item wasn't already seen - handleToggle: only call onSeen when the item is still unread (isNew) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6c47038 to
de68c17
Compare
…animation When closing an expanded item, the description preview was appearing in the header immediately (as expanded became false), while the image was still visible inside the animating Collapse — causing a visual jump. Fix: hide the preview on toggle and restore it only after onExited fires (animation fully complete). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ransition Instead of mounting/unmounting the description preview (which caused a height jump when it appeared), always keep it in the DOM and transition opacity only. Header height stays constant throughout the animation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opacity-only approach left an invisible gap in the expanded header. Also transition max-height and margin-top so the description takes zero space when not shown. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Animating the preview in/out caused layout issues no matter the approach. The title is sufficient for identification in collapsed state; the full description is visible on expand. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass setIsOpen to WhatsNewItemCollapsed and add the same onClick handler used in WhatsNewItem — clicking a '#'-prefixed CTA URL now closes the drawer, consistent with the featured/regular item behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…24809] (elementor#36366) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## PR Type - [x] Bugfix ## Summary This PR can be summarized in the following changelog entry: * Fix: WP Admin upgrade CTAs now use the correct `upgrade-one-wp-menu` UTM instead of the legacy `wp-menu` UTM. ## Description ### Root cause After the 10th birthday sale ended (ED-24386), non-sale upgrade paths in Elementor core still pointed at the legacy short link `https://go.elementor.com/pro-admin-menu/` (`utm_source=wp-menu`). Editor One / wp-one-package already uses the correct link (`https://go.elementor.com/go-pro-upgrade-one-wp-menu/` → `utm_source=upgrade-one-wp-menu`), but core `Go_Pro_Promotion_Item` was never updated when the legacy `go_elementor_pro` menu was removed (ED-22438). ### Why only certain users? | Path | URL source | UTM before fix | |------|------------|----------------| | Editor One upgrade submenu (`elementor-one-upgrade`) | wp-one-package | Correct | | Conversion banner (post-sale) | `Go_Pro_Promotion_Item::get_url()` | **Old** | | Legacy `go_elementor_pro` redirect / bookmarks | `Go_Pro_Promotion_Item::get_url()` | **Old** | | Connected One users (no upgrade submenu) | Other CTAs using core URL | **Old** | During the birthday sale, the conversion banner used a separate sale URL, so the stale UTM resurfaced once `is_sale_time()` returned false. ### Changes 1. Update `Go_Pro_Promotion_Item::URL` to `https://go.elementor.com/go-pro-upgrade-one-wp-menu/` 2. Extend `handle_external_redirects()` to handle both `go_elementor_pro` and `elementor-one-upgrade` 3. Update admin JS/SCSS/tracking to support **both** legacy and Editor One upgrade menu slugs (BC: Core can be lower than Pro) ### Backward compatibility All client-side selectors and tracking now cover both paths: - Legacy: `go_elementor_pro` under `#toplevel_page_elementor` - Editor One: `elementor-one-upgrade` under `#toplevel_page_elementor-home` The shared `Go_Pro_Promotion_Item::URL` update fixes the UTM for both paths, including conversion banner and legacy redirects. ### Note Ticket requested PM approval from Doron Wolf Morrison before replacing the UTM. This PR implements the UTM specified in ED-24809. Fixes ED-24809 ## Test instructions 1. On a free Elementor install with Editor One active, open WP Admin and click **Upgrade** under the Elementor menu. 2. Confirm redirect goes to `https://elementor.com/pro/?utm_source=upgrade-one-wp-menu&utm_medium=wp-dash&utm_campaign=gopro`. 3. On a page showing the conversion banner (post-sale), click **Upgrade Now** and confirm the same UTM. 4. Visit `wp-admin/admin.php?page=go_elementor_pro` directly and confirm the same redirect. 5. On a setup with legacy `go_elementor_pro` menu still present (older Core), confirm styling, new-tab behavior, and tracking still work. ## Quality assurance - [x] I have tested this code to the best of my abilities - [ ] I have added unittests to verify the code works as intended - [ ] Docs have been added / updated (for bug fixes / features) <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-66e5f9ae-a795-4f23-b8b0-f4e47a43ccd0"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-66e5f9ae-a795-4f23-b8b0-f4e47a43ccd0"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Netanel Baba <Ntnelbaba@users.noreply.github.com>
…ED-24820] (elementor#36368) ## Summary - Remove redundant per-event `app_type` from all editor event dispatch payloads across legacy JS, packages, and onboarding analytics. - Keep `appType: 'Editor'` registered via events-manager `enableTracking()` as the single source of truth for editor context on every event. - `window_name` and `appTypes` config entries are unchanged — still used for context-specific window identification. ## Test plan - [x] `npm run test:jest -- --testPathPattern=editor-one-events-wpdash` - [ ] Verify dispatched events in editor still include `appType: Editor` via super property (no per-event `app_type`) - [ ] Smoke-test publish dropdown, page list, onboarding, and pro-install connect flows Ref: [ED-24820](https://elementor.atlassian.net/browse/ED-24820) Made with [Cursor](https://cursor.com) [ED-24820]: https://elementor.atlassian.net/browse/ED-24820?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!--start_gitstream_placeholder--> ### ✨ PR Description ## 1. Problem & Context Consolidating analytics tracking by removing redundant per-event `app_type` property across the codebase. The events-manager now handles this as a super property (ED-24820), eliminating duplication. ## 2. What Changed (Where) | File | Change | |------|--------| | onboarding events | Removed `app_type: 'editor'` from interface and tracking payload | | editor-app-bar hooks (5 files) | Removed `app_type` from event payloads | | editor-interactions, editor-controls tracking | Removed `app_type` from base event properties | | document delete command, editor-one-events | Removed `app_type` from event data | | pro-install events | Removed `app_type` from 4 tracking calls | | test file | Updated assertions to expect payloads without `app_type` | ## 3. How It Works Events previously included `app_type: 'editor'` at point of dispatch. With this change, `app_type` is now injected by the events-manager as a super property, applying uniformly across all events without repetition in individual tracking calls. ## 4. Risks Low risk—purely removes redundant payload fields already centralized in events-manager. Verify events-manager super property implementation correctly injects `app_type` to ensure backward compatibility in analytics pipelines. _Generated by LinearB AI and added by gitStream._ <sub>AI-generated content may contain inaccuracies. Please verify before using. 💡 **Tip:** You can customize your AI Description using **Guidelines** [Learn how](https://docs.gitstream.cm/automation-actions/#describe-changes)</sub> <!--end_gitstream_placeholder--> Co-authored-by: Cursor <cursoragent@cursor.com>
…dgets\Utils [ED-24446] (elementor#36356) Co-authored-by: ElementorBot <48412871+elementorbot@users.noreply.github.com>
## PR Checklist <!-- Please check if your PR fulfills the following requirements: **Filling out the template is required.** Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. --> - [ ] The commit message follows our guidelines: https://github.com/elementor/elementor/blob/master/.github/CONTRIBUTING.md ## PR Type What kind of change does this PR introduce? <!-- Please check the one that applies to this PR using "x" with no spaces eg: [x]. --> - [ ] Bugfix - [ ] Feature - [ ] Code style update (formatting, local variables) - [ ] Refactoring (no functional changes, no api changes) - [ ] Build related changes - [ ] CI related changes - [ ] Documentation content changes - [ ] Other... Please describe: ## Summary This PR can be summarized in the following changelog entry: * ## Description An explanation of what is done in this PR * ## Test instructions This PR can be tested by following these steps: * ## Quality assurance - [ ] I have tested this code to the best of my abilities - [ ] I have added unittests to verify the code works as intended - [ ] Docs have been added / updated (for bug fixes / features) Fixes # <!--start_gitstream_placeholder--> ### ✨ PR Description ## 1. Problem & Context Automates cleanup of stale feature branches to reduce repository clutter. Runs weekly on Mondays at 3 AM UTC with manual override capability. ## 2. What Changed (Where) - `.github/workflows/remove-stale-branches.yml`: New workflow that identifies and removes branches not updated in 90+ days, excluding active PRs and protected branches. ## 3. How It Works Workflow builds exempt regex from open PR head refs plus version patterns (main/master/semver), then delegates removal to `fpicalausa/remove-stale-branches@v1.6.0` action. Operator notification happens via stale comments before deletion window. ## 4. Risks Token permissions sufficient but workflow runs unattended—misconfigured regex or exempt pattern could delete important branches. Mitigation: dry-run mode defaults to true for manual triggers; configurable grace periods via repo vars. _Generated by LinearB AI and added by gitStream._ <sub>AI-generated content may contain inaccuracies. Please verify before using. 💡 **Tip:** You can customize your AI Description using **Guidelines** [Learn how](https://docs.gitstream.cm/automation-actions/#describe-changes)</sub> <!--end_gitstream_placeholder--> --------- Co-authored-by: ElementorBot <48412871+elementorbot@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…344] (elementor#36401) ## Summary - `elementor-kit-mcp` fetched `GET /angie/v1/elementor-kit/schema` **eagerly during MCP server construction** (before waiting for the Angie SDK). Those `angie/v1/elementor-kit/*` routes are registered by the Angie plugin, not core — so when Angie is inactive the call returned `404 rest_no_route` on **every editor boot**, causing slow load / white screen. - Moved the schema fetch out of construction and into the schema resource template's lazy `list` callback, mirroring the sibling `elementor-v3-mcp` server (which does no eager network calls). The schema is now fetched only once Angie connects and lists resources — the exact case where the routes exist. - With Angie inactive, `sdk.waitForReady()` never resolves, so the server is never registered and the schema route is never called → no 404, no boot-time network cost. - Added a unit test (`__tests__/elementor-kit-mcp-server.test.ts`) asserting the schema endpoint is **not** hit during construction, and **is** fetched lazily when resources are listed. ## Test plan - [ ] `cd packages && npx jest core/elementor-kit-mcp` passes. - [ ] **Angie inactive:** open the editor without the Angie plugin; confirm (DevTools Network) no `rest_route=/angie/v1/elementor-kit/schema` request fires on boot and no `rest_no_route` 404 appears; editor loads without the slow-load/white-screen delay. - [ ] **Angie active:** open the editor with Angie active; exercise the kit MCP flow (list kit schema tabs / update kit settings) and confirm it still works (schema fetched lazily). ## Jira [ED-24344](https://elementor.atlassian.net/browse/ED-24344) [ED-24344]: https://elementor.atlassian.net/browse/ED-24344?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!--start_gitstream_placeholder--> ### ✨ PR Description ## 1. Problem & Context Schema fetch on server boot was causing 404 errors when Angie API wasn't ready yet. Deferring it to lazy-load on first resource list request avoids this. ## 2. What Changed (Where) - **elementor-kit-mcp-server.ts**: Moved `getAvailableTabs()` call inside `list()` callback; was executing synchronously at boot. - **elementor-kit-mcp-server.test.ts**: Added test suite verifying schema isn't fetched during construction, only on resource listing. ## 3. How It Works Schema fetch now happens inside the `list` async callback (line 220) instead of at module initialization. When a client requests available resources, `getAvailableTabs()` executes and populates the resource map—eliminating the premature 404. ## 4. Risks None identified. Lazy loading is safer (defers external dependency call) and test coverage validates both boot-time non-execution and lazy-load execution paths. _Generated by LinearB AI and added by gitStream._ <sub>AI-generated content may contain inaccuracies. Please verify before using. 💡 **Tip:** You can customize your AI Description using **Guidelines** [Learn how](https://docs.gitstream.cm/automation-actions/#describe-changes)</sub> <!--end_gitstream_placeholder-->
## PR Checklist <!-- Please check if your PR fulfills the following requirements: **Filling out the template is required.** Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. --> - [ ] The commit message follows our guidelines: https://github.com/elementor/elementor/blob/master/.github/CONTRIBUTING.md ## PR Type What kind of change does this PR introduce? <!-- Please check the one that applies to this PR using "x" with no spaces eg: [x]. --> - [ ] Bugfix - [ ] Feature - [ ] Code style update (formatting, local variables) - [ ] Refactoring (no functional changes, no api changes) - [ ] Build related changes - [ ] CI related changes - [ ] Documentation content changes - [ ] Other... Please describe: ## Summary This PR can be summarized in the following changelog entry: * ## Description An explanation of what is done in this PR * ## Test instructions This PR can be tested by following these steps: * ## Quality assurance - [ ] I have tested this code to the best of my abilities - [ ] I have added unittests to verify the code works as intended - [ ] Docs have been added / updated (for bug fixes / features) Fixes #
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… expanded Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
listLabelfield on the featured notification — plain divider is rendered when omittede-notification-item-seenwindow eventseenItemIdsstate is lifted toWhatsNewso it survives drawer close/reopen within a sessioninitialHasUnreadflag (captured once at page load from PHP) suppresses unread dots after a page refresh when there are no unread itemsunread_count(integer) alongsideis_unread(boolean) in the JS config; private helper eliminates duplication inOptionsTest plan
?reset_notifications=1, reload — badge shows unread countlistLabelon featured notification — divider shows the custom label textlistLabel— divider is plain with no text🤖 Generated with Claude Code